package com.xtinno.prompt;

import java.util.Map;

/**
 * 这个类包含了对 提示词（prompt）的通用操作.
 *
 * @author lizhen
 * @since 1.0.0
 */
public class PromptFormat {
	// 提示词的模版.
	String promptTemplate;

	/**
	 * <p>
	 *     使用提示词模版初始化对象，示例：
	 *
	 * <pre>{@code
	 *     给定下面的文本，帮我从里面提取当事人的姓名：
	 *     {content}
	 * }</pre>
	 *
	 * <p>
	 *     示例文本中的 <i>{content}</i> 就是可以杯替换的文本的占位符.
	 *
	 * @param promptTemplate 提示词模版.
	 */
	public PromptFormat(String promptTemplate) {
		this.promptTemplate = promptTemplate;
	}

	/**
	 * 使用传入的参数，填充提示词模版中的占位符，这个方法会把提示词模版修改为填充操作后的结果.
	 *
	 * @implSpec
	 * 下面给出一个例子，先初始化提示词模版，然后使用参数对模版的占位符做替换，替换后的 PromptFormat 对象包含的提示词被永久的改变了.
	 * <pre>{@code
	 *     PromptFormat format = new PromptFormat("给定下面的文本，帮我从里面提取当事人的姓名：{content}");
	 *     PromptFormat formated = format.fill({"content": "张三，男，2000年，山东人。"});
	 *     formated.getPrompt(); --> "给定下面的文本，帮我从里面提取当事人的姓名：张三，男，2000年，山东人。"
	 * }</pre>
	 *
	 * @param variables 传入的参数.
	 * @return 替换提示词后的对象.
	 *
	 * @see PromptFormat#getPrompt()
	 */
	public PromptFormat fill(Map<String, String> variables) {
		for (Map.Entry<String, String> entry : variables.entrySet()) {
			String placeholder = "{" + entry.getKey() + "}";
			String value = entry.getValue() != null ? entry.getValue() : "";
			promptTemplate = promptTemplate.replace(placeholder, value);
		}
		return this;
	}

	/**
	 * look {@link #fill(Map)}.这个就是 map 参数的 key 和 value 的版本.
	 * @param key map key.
	 * @param value map value.
	 * @return 替换提示词后的对象.
	 */
	public PromptFormat fill(String key, String value) {
		String placeholder = "{" + key + "}";
		value = value != null ? value : "";
		promptTemplate = promptTemplate.replace(placeholder, value);
		return this;
	}

	/**
	 * 使用传入的参数，替换提示词模版中的占位符，这个方法不会改变现有的提示词模版，只是做完参数替换后，返回替换的结果.
	 *
	 * @implSpec
	 * 下面给出一个例子，先初始化提示词模版，然后使用参数对模版的占位符做替换，替换后的 PromptFormat 对象包含的提示词还是初始化的那个提示词.
	 * <pre>{@code
	 *     PromptFormat format = new PromptFormat("给定下面的文本，帮我从里面提取当事人的姓名：{content}");
	 *     String formated = format.format({"content": "张三，男，2000年，山东人。"});
	 *     formated --> "给定下面的文本，帮我从里面提取当事人的姓名：张三，男，2000年，山东人。"
	 *     format.getPrompt(); --> "给定下面的文本，帮我从里面提取当事人的姓名：{content}"
	 * }</pre>
	 *
	 * @param variables 传入的参数.
	 * @return 输出替换后的提示词.
	 */
	public String format(Map<String, String> variables) {
		String tmp = promptTemplate;
		for (Map.Entry<String, String> entry : variables.entrySet()) {
			String placeholder = "{" + entry.getKey() + "}";
			String value = entry.getValue() != null ? entry.getValue() : "";
			tmp = tmp.replace(placeholder, value);
		}
		return tmp;
	}

	/**
	 * {@link PromptFormat#format(Map)} 方法的重载，就是对应 1个 key 和 1个 value 的情况，就没必要非要传入一个 map.
	 *
	 * @param key variables key.
	 * @param value variables value.
	 * @return 输出替换后的提示词.
	 */
	public String format(String key, String value) {
		String placeholder = "{" + key + "}";
		value = value != null ? value : "";
		return promptTemplate.replace(placeholder, value);
	}

	/**
	 * 获取当前对象所代表的提示词，初始化后的返回结果就是，传入的提示词模版的值，如果有调用过 {@link PromptFormat#fill(Map)} 方法
	 * 会对这个造成影响，但是，调用 {@link PromptFormat#format(Map)} 方法不会对这个造成影响.
	 *
	 * @return 返回提示词.
	 *
	 * @see PromptFormat#format(Map)
	 */
	public String getPrompt() {
		return this.promptTemplate;
	}
}
